<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>雅思备考助手 (Vue Version)</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <style>
    .nav-button {
      position: relative;
      padding: 8px 16px;
      font-weight: 500;
      color: #475569;
      /* text-slate-600 */
      transition: color 0.3s;
    }

    .nav-button::after {
      content: '';
      position: absolute;
      bottom: 0;
      left: 50%;
      transform: translateX(-50%);
      width: 0;
      height: 2px;
      background-color: #3b82f6;
      /* bg-blue-500 */
      transition: width 0.3s;
    }

    .nav-button:hover {
      color: #1e293b;
      /* text-slate-800 */
    }

    .nav-button:hover::after {
      width: 100%;
    }

    [v-cloak] {
      display: none;
    }
  </style>
</head>

<body class="bg-slate-100">

  <div id="app" v-cloak>
    <div class="container mx-auto p-4 md:p-8">
      <app-header @set-view="setCurrentView"></app-header>
      <main class="mt-8">
        <component :is="currentViewComponent" @set-view="setCurrentView"></component>
      </main>
      <app-footer></app-footer>
    </div>
  </div>

  <script>
    const { createApp, ref, computed } = Vue;

    // --- SVG Icons ---
    const icons = {
      BookOpen: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-white"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"/><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"/></svg>`,
      Headphones: `<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-blue-500"><path d="M3 14h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7a9 9 0 0 1 18 0v7a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3"/></svg>`,
      FileText: `<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-green-500"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><line x1="10" y1="9" x2="8" y2="9"/></svg>`,
      Pencil: `<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-orange-500"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/><path d="m15 5 4 4"/></svg>`,
      Mic: `<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-red-500"><path d="M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="22"/></svg>`,
      Lightbulb: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-yellow-400"><path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 9 5c0 1.3.5 2.6 1.5 3.5.7.8 1.3 1.5 1.5 2.5"/><path d="M9 18h6"/><path d="M10 22h4"/></svg>`,
      Clock: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-indigo-400"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>`,
      BarChart2: `<svg xmlns="http://www.w3.org/2000/svg" width="150" height="150" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-slate-400"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg>`
    };

    // --- Component Definitions ---

    const AppHeader = {
      template: `
            <header class="bg-white rounded-xl shadow-md p-4 flex justify-between items-center">
                <div class="flex items-center gap-3 cursor-pointer" @click="$emit('setView', 'Dashboard')">
                    <div class="bg-blue-500 p-2 rounded-lg" v-html="icons.BookOpen"></div>
                    <h1 class="text-xl md:text-2xl font-bold text-slate-700">雅思备考助手</h1>
                </div>
                <nav class="hidden md:flex gap-4">
                    <button @click="$emit('setView', 'ListeningPractice')" class="nav-button">听力</button>
                    <button @click="$emit('setView', 'ReadingPractice')" class="nav-button">阅读</button>
                    <button @click="$emit('setView', 'WritingPractice')" class="nav-button">写作</button>
                    <button @click="$emit('setView', 'SpeakingPractice')" class="nav-button">口语</button>
                </nav>
            </header>
        `,
      data() { return { icons } }
    };

    const AppFooter = {
      template: `
            <footer class="text-center mt-12 text-sm text-slate-400">
                <p>&copy; 2025 雅思备考助手. 祝您学习愉快!</p>
            </footer>
        `
    };

    const ModuleCard = {
      props: ['icon', 'title', 'description'],
      template: `
            <div @click="$emit('click')" class="bg-white p-6 rounded-xl shadow-md hover:shadow-lg hover:-translate-y-1 transition-all duration-300 cursor-pointer flex flex-col items-center text-center">
                <div class="mb-4" v-html="icon"></div>
                <h3 class="text-lg font-bold text-slate-700">{{ title }}</h3>
                <p class="text-slate-500 text-sm mt-2">{{ description }}</p>
            </div>
        `
    };

    const TipCard = {
      props: ['icon', 'title', 'content', 'isHtml'],
      template: `
            <div class="bg-white p-6 rounded-xl shadow-sm">
                <div class="flex items-center mb-3">
                    <div v-html="icon"></div>
                    <h4 class="ml-3 font-bold text-slate-600">{{ title }}</h4>
                </div>
                <div class="text-slate-500 text-sm" v-if="isHtml" v-html="content"></div>
                <div class="text-slate-500 text-sm" v-else>{{ content }}</div>
            </div>
        `
    };

    const Dashboard = {
      components: { ModuleCard, TipCard },
      template: `
            <div>
                <div class="bg-white p-6 rounded-xl shadow-sm text-center mb-8">
                    <h2 class="text-2xl font-bold text-blue-600">欢迎来到您的雅思备考中心</h2>
                    <p class="text-slate-500 mt-2">选择一个模块开始练习，祝您考试成功！</p>
                </div>
                <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
                    <module-card 
                        :icon="icons.Headphones"
                        title="听力练习"
                        description="模拟真实考试场景，提升听力技巧。"
                        @click="$emit('setView', 'ListeningPractice')"
                    />
                    <module-card 
                        :icon="icons.FileText"
                        title="阅读练习"
                        description="精选学术文章，挑战各类题型。"
                        @click="$emit('setView', 'ReadingPractice')"
                    />
                    <module-card 
                        :icon="icons.Pencil"
                        title="写作练习"
                        description="练习图表和议论文，附带范文参考。"
                        @click="$emit('setView', 'WritingPractice')"
                    />
                    <module-card 
                        :icon="icons.Mic"
                        title="口语练习"
                        description="模拟口语考试，提供常见话题和技巧。"
                        @click="$emit('setView', 'SpeakingPractice')"
                    />
                </div>
                <div class="mt-8 grid grid-cols-1 md:grid-cols-2 gap-6">
                    <tip-card 
                        :icon="icons.Lightbulb"
                        title="每日小贴士"
                        content="写作时，尽量使用多样的句式结构。例如，可以交替使用简单句、复合句和复杂句来展示你的语言能力。"
                    />
                    <tip-card 
                        :icon="icons.Clock"
                        title="今日词汇"
                        :isHtml="true"
                        content="<div><p class='font-bold'>Ubiquitous (adj.)</p><p>普遍存在的，无处不在的。例句：Mobile phones have become ubiquitous in modern society.</p></div>"
                    />
                </div>
            </div>
        `,
      data() { return { icons } },
    };

    const ListeningPractice = {
      template: `
            <div class="bg-white p-6 rounded-xl shadow-md">
                <h2 class="text-2xl font-bold mb-4 text-blue-600">听力练习: Section 1</h2>
                <div class="mb-6 p-4 bg-slate-50 rounded-lg">
                    <p class="font-semibold mb-2">音频播放器</p>
                    <div class="w-full bg-slate-200 rounded-lg h-12 flex items-center justify-center">
                        <p class="text-slate-500">(此处为音频播放器占位符 - 请使用您自己的听力材料)</p>
                    </div>
                </div>
                <div class="space-y-6">
                    <div>
                        <label class="block font-semibold mb-2">1. The student is looking for the main 
                            <input type="text" v-model="answers.q1" class="border-b-2 border-slate-300 focus:border-blue-500 outline-none w-24 mx-2 text-center" />.
                        </label>
                        <p v-if="showResults" class="text-sm mt-1" :class="answers.q1.toLowerCase() === correctAnswers.q1 ? 'text-green-600' : 'text-red-600'">正确答案: {{correctAnswers.q1}}</p>
                    </div>
                    <div>
                        <p class="font-semibold mb-2">2. What time does the library close on Saturdays?</p>
                        <div class="space-y-2">
                            <label v-for="(option, index) in q2Options" :key="index" class="flex items-center">
                                <input type="radio" name="q2" :value="option.value" v-model="answers.q2" class="mr-2"/>
                                {{ option.value }}. {{ option.text }}
                            </label>
                        </div>
                        <p v-if="showResults" class="text-sm mt-1" :class="answers.q2 === correctAnswers.q2 ? 'text-green-600' : 'text-red-600'">正确答案: {{correctAnswers.q2}} (5 PM)</p>
                    </div>
                </div>
                <div class="mt-8 flex gap-4">
                    <button @click="showResults = true" class="bg-blue-500 text-white px-6 py-2 rounded-lg hover:bg-blue-600 transition-colors">检查答案</button>
                    <button @click="reset" class="bg-slate-200 text-slate-700 px-6 py-2 rounded-lg hover:bg-slate-300 transition-colors">重置</button>
                </div>
            </div>
        `,
      data() {
        return {
          answers: { q1: '', q2: '' },
          showResults: false,
          correctAnswers: { q1: 'library', q2: 'B' },
          q2Options: [
            { value: 'A', text: '4 PM' },
            { value: 'B', text: '5 PM' },
            { value: 'C', text: '6 PM' }
          ]
        }
      },
      methods: {
        reset() {
          this.answers = { q1: '', q2: '' };
          this.showResults = false;
        }
      }
    };

    const ReadingPractice = {
      template: `
            <div class="bg-white p-6 rounded-xl shadow-md">
                <h2 class="text-2xl font-bold mb-4 text-green-600">阅读练习: Passage 1</h2>
                <div class="p-4 border rounded-lg bg-slate-50 max-h-60 overflow-y-auto mb-6">
                    <h3 class="font-bold text-lg mb-2">The Rise of Artificial Intelligence</h3>
                    <p class="text-slate-600 text-sm leading-relaxed">
                        Artificial Intelligence (AI) is a broad area of computer science that makes machines seem like they have human intelligence... (text content same as React version)
                    </p>
                </div>
                <h3 class="font-bold text-lg mb-4">判断题 (True / False / Not Given)</h3>
                <div class="space-y-4">
                    <div v-for="(q, index) in questions" :key="index" class="md:flex md:items-center md:justify-between p-3 bg-slate-50 rounded-lg">
                        <p class="mb-2 md:mb-0"><span class="font-bold">{{index + 1}}.</span> {{q.text}}</p>
                        <div class="flex items-center gap-2">
                            <select v-model="answers['q'+(index+1)]" class="border border-slate-300 rounded-md px-3 py-1">
                                <option value="">选择...</option>
                                <option value="TRUE">True</option>
                                <option value="FALSE">False</option>
                                <option value="NOT GIVEN">Not Given</option>
                            </select>
                            <p v-if="showResults" class="text-sm" :class="answers['q'+(index+1)] === q.correct ? 'text-green-600' : 'text-red-600'">正确: {{q.correct}}</p>
                        </div>
                    </div>
                </div>
                <div class="mt-8 flex gap-4">
                    <button @click="showResults = true" class="bg-green-500 text-white px-6 py-2 rounded-lg hover:bg-green-600 transition-colors">检查答案</button>
                    <button @click="reset" class="bg-slate-200 text-slate-700 px-6 py-2 rounded-lg hover:bg-slate-300 transition-colors">重置</button>
                </div>
            </div>
        `,
      data() {
        return {
          answers: { q1: '', q2: '' },
          showResults: false,
          questions: [
            { text: 'AI research aims to replicate various aspects of human intelligence.', correct: 'TRUE' },
            { text: 'General AI has already been achieved by several tech companies.', correct: 'NOT GIVEN' }
          ]
        }
      },
      methods: {
        reset() {
          this.answers = { q1: '', q2: '' };
          this.showResults = false;
        }
      }
    };

    const WritingPractice = {
      template: `
            <div class="bg-white p-6 rounded-xl shadow-md">
                <h2 class="text-2xl font-bold mb-4 text-orange-600">写作练习</h2>
                <div class="flex border-b mb-4">
                    <button @click="task = 'TASK_1'" :class="['px-4 py-2', task === 'TASK_1' ? 'border-b-2 border-orange-500 font-semibold text-orange-600' : 'text-slate-500']">Task 1: 图表描述</button>
                    <button @click="task = 'TASK_2'" :class="['px-4 py-2', task === 'TASK_2' ? 'border-b-2 border-orange-500 font-semibold text-orange-600' : 'text-slate-500']">Task 2: 议论文</button>
                </div>

                <div v-if="task === 'TASK_1'">
                    <h3 class="font-semibold text-lg mb-2">Task 1: The chart below shows the changes in three different areas of crime...</h3>
                    <p class="text-slate-500 mb-4">Summarise the information... Write at least 150 words.</p>
                    <div class="flex justify-center items-center bg-slate-50 p-4 rounded-lg mb-4">
                        <div v-html="icons.BarChart2"></div>
                        <p class="ml-4 text-slate-500">(此处为图表占位符)</p>
                    </div>
                    <textarea @input="updateWordCount" class="w-full h-48 p-3 border rounded-lg focus:ring-2 focus:ring-orange-300 focus:outline-none" placeholder="在此处开始写作..."></textarea>
                    <p class="text-right text-sm text-slate-500 mt-2">字数: {{ wordCount }}</p>
                    <details class="mt-4">
                        <summary class="cursor-pointer font-semibold text-orange-600">查看范文</summary>
                        <div class="p-4 mt-2 bg-slate-50 rounded-lg border text-sm text-slate-600">
                           <p>The bar chart illustrates...</p>
                        </div>
                    </details>
                </div>

                <div v-if="task === 'TASK_2'">
                    <h3 class="font-semibold text-lg mb-2">Task 2: Some people believe that unpaid community service should be a compulsory part...</h3>
                    <p class="text-slate-500 mb-4">Give reasons for your answer... Write at least 250 words.</p>
                    <textarea @input="updateWordCount" class="w-full h-64 p-3 border rounded-lg focus:ring-2 focus:ring-orange-300 focus:outline-none" placeholder="在此处开始写作..."></textarea>
                    <p class="text-right text-sm text-slate-500 mt-2">字数: {{ wordCount }}</p>
                     <details class="mt-4">
                        <summary class="cursor-pointer font-semibold text-orange-600">查看范文</summary>
                        <div class="p-4 mt-2 bg-slate-50 rounded-lg border text-sm text-slate-600">
                           <p>The integration of mandatory community service...</p>
                        </div>
                    </details>
                </div>
            </div>
        `,
      data() {
        return {
          task: 'TASK_1',
          wordCount: 0,
          icons,
        }
      },
      methods: {
        updateWordCount(e) {
          const text = e.target.value;
          this.wordCount = text.trim().split(/\s+/).filter(Boolean).length;
        }
      },
      watch: {
        task() {
          this.wordCount = 0;
          // Ideally, you'd clear the textarea, but we have two separate ones.
        }
      }
    };

    const SpeakingSection = {
      props: ['part', 'title', 'questions', 'tip'],
      template: `
            <div>
                <h3 class="text-xl font-bold text-slate-700">{{ part }}: {{ title }}</h3>
                <div class="mt-3 p-4 bg-slate-50 rounded-lg border border-l-4 border-red-400">
                    <ul class="list-disc list-inside space-y-2 text-slate-600">
                        <li v-for="(q, i) in questions" :key="i">{{ q }}</li>
                    </ul>
                </div>
                <div class="mt-3 p-3 bg-yellow-50 text-yellow-800 rounded-lg text-sm">
                    <span class="font-bold">💡 提示:</span> {{ tip }}
                </div>
            </div>
        `
    };

    const SpeakingPractice = {
      components: { SpeakingSection },
      template: `
            <div class="bg-white p-6 rounded-xl shadow-md">
                <h2 class="text-2xl font-bold mb-4 text-red-600">口语练习</h2>
                <div class="space-y-8">
                    <speaking-section 
                        part="Part 1"
                        title="常见问题"
                        :questions="part1Questions"
                        tip="回答Part 1时，尽量给出2-3句话的扩展回答，不要只用一个词回答。"
                    />
                    <speaking-section 
                        part="Part 2"
                        title="话题卡"
                        :questions="part2Questions"
                        tip="你有1分钟准备时间，然后需要说1-2分钟。在准备时，记下关键词而不是整个句子。"
                    />
                    <speaking-section 
                        part="Part 3"
                        title="深入讨论"
                        :questions="part3Questions"
                        tip="Part 3是与考官的双向讨论。你需要给出更深入、更有条理的观点，并进行论证。"
                    />
                </div>
            </div>
        `,
      data() {
        return {
          part1Questions: [
            "Let's talk about your hometown. Where is it?",
            "What do you like about it?",
            "Do you work or are you a student?"
          ],
          part2Questions: [
            "Describe a website you have bought something from.",
            "You should say:",
            "- what the website is",
            "- what you bought from this website",
            "- how satisfied you were with what you bought",
            "and explain what you liked or disliked about using this website."
          ],
          part3Questions: [
            "What are the advantages and disadvantages of online shopping?",
            "How has online shopping changed our lives?",
            "Do you think online shopping will replace physical stores in the future?"
          ]
        }
      }
    };

    // --- Main App ---
    const app = createApp({
      data() {
        return {
          currentView: 'Dashboard' // Initial view
        }
      },
      components: {
        AppHeader,
        AppFooter,
        Dashboard,
        ListeningPractice,
        ReadingPractice,
        WritingPractice,
        SpeakingPractice
      },
      computed: {
        currentViewComponent() {
          // Maps the string name to the component object
          return this.currentView;
        }
      },
      methods: {
        setCurrentView(viewName) {
          this.currentView = viewName;
        }
      }
    });

    app.mount('#app');

  </script>
</body>

</html>